package com.apimanage.gateway.filter;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.apimanage.gateway.config.IpFilterProperties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * IP过滤过滤器
 * 用于实现IP黑白名单功能
 */
@Component
@Slf4j
public class IpFilter implements GlobalFilter, Ordered {

    @Autowired
    private IpFilterProperties ipFilterProperties;

    private final AntPathMatcher pathMatcher = new AntPathMatcher();

    /**
     * 黑名单模式
     */
    private static final String MODE_BLACKLIST = "blacklist";

    /**
     * 白名单模式
     */
    private static final String MODE_WHITELIST = "whitelist";

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 如果IP过滤功能未启用，则直接通过
        if (!ipFilterProperties.isEnabled()) {
            return chain.filter(exchange);
        }

        // 获取请求路径
        String path = exchange.getRequest().getURI().getPath();
        
        // 检查是否为不需要过滤的路径
        if (isExcludePath(path)) {
            log.debug("[IpFilter] Path '{}' is in exclude list, skipping IP filter", path);
            return chain.filter(exchange);
        }

        // 获取客户端IP
        String clientIp = getClientIp(exchange.getRequest());
        log.debug("[IpFilter] Processing request from IP: '{}' for path: '{}'", clientIp, path);

        // 根据模式进行IP过滤
        boolean isAllowed = isIpAllowed(clientIp);
        if (!isAllowed) {
            log.warn("[IpFilter] IP '{}' is denied access to path: '{}' in {} mode", 
                     clientIp, path, ipFilterProperties.getMode());
            exchange.getResponse().setStatusCode(HttpStatus.FORBIDDEN);
            return exchange.getResponse().setComplete();
        }

        return chain.filter(exchange);
    }

    /**
     * 根据配置模式检查IP是否允许访问
     */
    private boolean isIpAllowed(String clientIp) {
        String mode = ipFilterProperties.getMode();
        
        if (MODE_BLACKLIST.equalsIgnoreCase(mode)) {
            // 黑名单模式：如果IP在黑名单中，则拒绝访问
            return !isIpInList(clientIp, ipFilterProperties.getBlacklist());
        } else if (MODE_WHITELIST.equalsIgnoreCase(mode)) {
            // 白名单模式：只有IP在白名单中，才允许访问
            return isIpInList(clientIp, ipFilterProperties.getWhitelist());
        } else {
            log.warn("[IpFilter] Unknown IP filter mode: '{}', allowing access by default", mode);
            return true;
        }
    }

    /**
     * 检查IP是否在指定列表中（支持通配符）
     */
    private boolean isIpInList(String clientIp, List<String> ipList) {
        if (CollUtil.isEmpty(ipList)) {
            return false;
        }
        
        // 如果客户端IP为空，默认拒绝
        if (StrUtil.isEmpty(clientIp)) {
            return false;
        }
        
        // 检查IP是否精确匹配或通配符匹配
        for (String ipPattern : ipList) {
            if (StrUtil.isEmpty(ipPattern)) {
                continue;
            }
            
            // 精确匹配
            if (ipPattern.equals(clientIp)) {
                return true;
            }
            
            // 通配符匹配（简单的*通配符）
            if (ipPattern.contains("*")) {
                String regexPattern = ipPattern.replace(".", "\\.")
                                              .replace("*", ".*");
                if (clientIp.matches(regexPattern)) {
                    return true;
                }
            }
        }
        
        return false;
    }

    /**
     * 获取客户端IP
     */
    private String getClientIp(org.springframework.http.server.reactive.ServerHttpRequest request) {
        // 从X-Forwarded-For头获取IP，或直接获取请求的远程地址
        String xForwardedFor = request.getHeaders().getFirst("X-Forwarded-For");
        if (StrUtil.isNotEmpty(xForwardedFor)) {
            // 多个IP时，取第一个
            return xForwardedFor.split(",")[0].trim();
        }
        return request.getRemoteAddress() != null ? request.getRemoteAddress().getAddress().getHostAddress() : "unknown";
    }

    /**
     * 检查路径是否在排除列表中
     */
    private boolean isExcludePath(String path) {
        List<String> excludePaths = ipFilterProperties.getExcludePaths();
        if (CollUtil.isNotEmpty(excludePaths)) {
            for (String pattern : excludePaths) {
                if (pathMatcher.match(pattern, path)) {
                    return true;
                }
            }
        }
        return false;
    }

    @Override
    public int getOrder() {
        // IP过滤器最先执行
        return -100;
    }
}